#region File Description
//-----------------------------------------------------------------------------
// GameplayScreen.cs
//
// Microsoft XNA Community Game Platform
// Copyright (C) Microsoft Corporation. All rights reserved.
//-----------------------------------------------------------------------------
#endregion

#region Using Statements
using System;
using System.Threading;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Audio;
using Particle3DSample;

#endregion

namespace GameStateManagement
{
    /// <summary>
    /// This screen implements the actual game logic. It is just a
    /// placeholder to get the idea across: you'll probably want to
    /// put some more interesting gameplay in here!
    /// </summary>
    class GameplayScreen : GameScreen
    {

        //Sound Variables
        //public static AudioEngine audio;
        //public static WaveBank wavebank;
        //public static SoundBank soundbank;

        public static Matrix CameraMatrix, ProjectionMatrix;

        //Lighting Variables
        public static Vector3 ambientLightColor, specularColor, diffuseDirection, diffuseColor;
        public static float specularPower;


        ContentManager content;
        SpriteFont gameFont;

        Random random = new Random();

        public static ChaseCamera camera;
        Ship ship;
        //Sphere sphere;
        Background background;
        DebrisSpawnManager spawnManager;


        Utils.Timer m_kTimer = new Utils.Timer();




        // Aaron's stuff
        SpriteBatch spriteBatch;

        ParticleSystem fireParticles;

        ////////May not need this?
        // Camera state.
        float cameraArc = -5;
        float cameraRotation = 0;
        float cameraDistance = 200;




        /// <summary>
        /// Constructor.
        /// </summary>
        public GameplayScreen()
        {
            //Content.RootDirectory = "Content";

            TransitionOnTime = TimeSpan.FromSeconds(1.5);
            TransitionOffTime = TimeSpan.FromSeconds(0.5);         

        }


        /// <summary>
        /// Load graphics content for the game.
        /// </summary>
        public override void LoadContent()
        {
            if (content == null)
                content = new ContentManager(ScreenManager.Game.Services, "Content");

            //Sound
            //audio = new AudioEngine("Content/Sounds.xgs");
            //wavebank = new WaveBank(audio, "Content/XNAsteroids Waves.xwb");
            //soundbank = new SoundBank(audio, "Content/XNAsteroids Cues.xsb");

            //Ship
            ship = new Ship(ScreenManager.Game);
            ScreenManager.Game.Components.Add(ship);
            ship.updateWorldTransformMatrix();

            /*sphere = new Sphere(ScreenManager.Game);
            sphere.updateWorldTransformMatrix();
            ScreenManager.Game.Components.Add(sphere);
            */
            background = new Background(ScreenManager.Game);
            ScreenManager.Game.Components.Add(background);

            spawnManager = new DebrisSpawnManager(ScreenManager.Game);
            ScreenManager.Game.Components.Add(spawnManager);

            fireParticles = new FireParticleSystem(ScreenManager.Game, content);
            ScreenManager.Game.Components.Add(fireParticles);

            //Camera
            camera = new ChaseCamera();

            // Set the camera offsets
            camera.DesiredPositionOffset = new Vector3(0.0f, 100.0f, 300.0f);
            camera.LookAtOffset = new Vector3(0.0f, 30.0f, 0.0f);

            // Set camera perspective
            camera.NearPlaneDistance = 0.1f;
            camera.FarPlaneDistance = 10000.0f;
            camera.AspectRatio = (float)ScreenManager.GraphicsDevice.Viewport.Width / ScreenManager.GraphicsDevice.Viewport.Height;
            updateCamera();
            camera.Reset();

            CameraMatrix = Matrix.CreateLookAt(new Vector3(0.0f, 0.0f, 1000.0f), Vector3.Zero, Vector3.UnitY);
            ProjectionMatrix = Matrix.CreatePerspectiveFieldOfView((float)Math.PI / 4.0f, 1.333f, 0.1f, 10000.0f);

            UpdateFire();

            //Lighting - Ambient
            ambientLightColor = Color.Gray.ToVector3();
            ambientLightColor.Normalize();
            ambientLightColor *= 0.3f;

            //Lightin - Diffuse
            diffuseColor = Color.Silver.ToVector3();
            diffuseColor.Normalize();
            diffuseColor *= 3.0f;
            diffuseDirection = new Vector3(0.3f, -0.7f, -0.6f);

            //Lighting - Specular
            specularColor = Color.Silver.ToVector3();
            specularColor.Normalize();
            specularColor *= 0.3f;
            specularPower = 100.0f;

            

            gameFont = content.Load<SpriteFont>("gamefont");

            


            // Loading Screen
            Thread.Sleep(1000);
            ScreenManager.Game.ResetElapsedTime();

           

 
        }

        public void updateCamera()
        {
            camera.ChasePosition = ship.Position;
            camera.ChaseDirection = ship.worldTransformMatrix.Forward;
            camera.Up = ship.worldTransformMatrix.Up;

            //camera.ChasePosition = debris.Position;
            //camera.ChaseDirection = debris.worldTransformMatrix.Forward;
            //camera.Up = debris.worldTransformMatrix.Up;
        }

        /// <summary>
        /// Helper for updating the fire effect.
        /// </summary>
        void UpdateFire()
        {
            const int fireParticlesPerFrame = 60;

            // Create a number of fire particles, randomly positioned around a circle.
            for (int i = 0; i < fireParticlesPerFrame; i++)
            {
                fireParticles.AddParticle(RandomPointOnCircle() + ship.Position, ship.worldTransformMatrix.Backward);
            }

            // Create one smoke particle per frame, too.
           // smokePlumeParticles.AddParticle(RandomPointOnCircle(), Vector3.Zero);
        }


        /// <summary>
        /// Helper used by the UpdateFire method. Chooses a random location
        /// around a circle, at which a fire particle will be created.
        /// </summary>
        Vector3 RandomPointOnCircle()
        {
            const float radius = 20;
            const float height = 15;

            double angle = random.NextDouble() * Math.PI * 2;

            float x = (float)Math.Cos(angle);
            float z = (float)Math.Sin(angle);

            return new Vector3(x * radius, z * radius + height, 0/*z * radius*/);
        }



        /// <summary>
        /// Unload graphics content used by the game.
        /// </summary>
        /// 
        public override void UnloadContent()
        {
            content.Unload();
        }


        /// <summary>
        /// Updates the state of the game. This method checks the GameScreen.IsActive
        /// property, so the game will stop updating when the pause menu is active,
        /// or if you tab away to a different application.
        /// </summary>
        public override void Update(GameTime gameTime, bool otherScreenHasFocus,
                                                       bool coveredByOtherScreen)
        {

            //spawnManager.updateRadius(sphere.getRadius());

            base.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);

            float dTime = ((float)gameTime.ElapsedGameTime.Ticks / System.TimeSpan.TicksPerMillisecond / 1000.0f);

            if (IsActive)
            {

                updateCamera();
                camera.Update(gameTime);

 

                m_kTimer.Update(gameTime);



            }
            UpdateFire();


        }


        /// <summary>
        /// Lets the game respond to player input. Unlike the Update method,
        /// this will only be called when the gameplay screen is active.
        /// </summary>
        public override void HandleInput(InputState input, GameTime gameTime)
        {
            float dTime = ((float)gameTime.ElapsedGameTime.Ticks / System.TimeSpan.TicksPerMillisecond / 1000.0f);
            if (input == null)
                throw new ArgumentNullException("input");

            if (input.PauseGame)
            {
                // If they pressed pause, bring up the pause menu screen.
                ScreenManager.AddScreen(new PauseMenuScreen());
            }
            else
            {
                if (!ship.forceBased)
                {
                    if (input.ShipUp)
                    {
                        ship.up(gameTime);
                    }
                    if (input.ShipDown)
                    {
                        ship.down(gameTime);
                    }
                    if (input.ShipLeft)
                    {
                        ship.left(gameTime);
                    }
                    if (input.ShipRight)
                    {
                        ship.right(gameTime);
                    }
                    if (input.ShipRotCW)
                    {
                        ship.cwrot(gameTime);
                    }
                    if (input.ShipRotCCW)
                    {
                        ship.ccwrot(gameTime);
                    }
                    if (input.ShipFireLeft)
                    {
                       // ship.fireLeft(gameTime, sphere.getRadius());
                    }
                    if (input.ShipFireRight)
                    {
                    //    ship.fireRight(gameTime, sphere.getRadius());
                    }
                }
                else
                {
                    if (input.ShipUp)
                    {
                        ship.up(gameTime);
                    }
                    else if (input.ShipDown)
                    {
                        ship.down(gameTime);
                    }
                    else
                    {
                        ship.verticalThrustOff();
                    }
                    if (input.ShipLeft)
                    {
                        ship.left(gameTime);
                    }
                    else if (input.ShipRight)
                    {
                        ship.right(gameTime);
                    }
                    else
                    {
                        ship.horizontalThrustOff();
                    }
                    if (input.ShipRotCW)
                    {
                        ship.cwrot(gameTime);
                    }
                    else if (input.ShipRotCCW)
                    {
                        ship.ccwrot(gameTime);
                    }
                    else
                    {
                        ship.rotationalThrustOff();
                    }
                    if (input.ShipFireLeft)
                    {
                        //ship.fireLeft(gameTime, sphere.getRadius());
                    }
                    if (input.ShipFireRight)
                    {
                        //ship.fireRight(gameTime, sphere.getRadius());
                    }

                }
                if (input.SwitchMove)
                {
                    ship.switchMove();
                }
                if (input.CamSwitch)
                {
                    ship.switchCam();
                    //sphere.switchCam();
                    background.switchCam();
                    spawnManager.switchCam();

                }

               
            }
        }


        /// <summary>
        /// Draws the gameplay screen.
        /// </summary>
        public override void Draw(GameTime gameTime)
        {

            ScreenManager.GraphicsDevice.Clear(Color.CornflowerBlue);

            spriteBatch = ScreenManager.SpriteBatch;

            spriteBatch.Begin();

            spriteBatch.End();

            // If the game is transitioning on or off, fade it out to black.
            if (TransitionPosition > 0)
                ScreenManager.FadeBackBufferToBlack(255 - TransitionAlpha);

            //Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.PiOver4, aspectRatio, 1, 10000);

            if (ship.followCam)
                fireParticles.SetCamera(camera.View, ProjectionMatrix);
            else
                fireParticles.SetCamera(CameraMatrix, ProjectionMatrix);
        }


    }
}
